/*****************************************************************************
*                     Organizacion de Datos - 75.06                          *
*                         Catedra Lic. Servetto                              *
*            Facultad de Ingenieria - Universidad de Buenos Aires            *
******************************************************************************/

#include "Integridad.h"

using namespace std;
using namespace Comun;

namespace CapaMetadata
{
	//RI representa a una relacion de integridad q se verifica en este momento
	//ValoresOLD lista de los valores(lista) q van a cambiar(pudiendo cambiar todos a uno de ellos)
	//Valores son los nuevos valores q se van a aplicar;
	bool Integridad::VerificarIntegridadBajaActualizacion(RelacionIntegridad& RI,list<Registro>* ValoresOld,list<ClaveValor>* Valores){
		if (RI.getTipoIntegridad()==iAlta) return true;

		for (list<Registro>::iterator it=ValoresOld->begin();it!=ValoresOld->end();++it){
			Registro& Reg=*it;
			list<ClaveValor> ValorControlaIntegridad;
			ClaveValor NuevoValorIntegridad;
			for (list<ClaveValor>::iterator itValores=Valores->begin();itValores!=Valores->end();++itValores){
				ClaveValor& Actual=*itValores;
				if (Actual.Clave==RI.getNombreCampo())
					NuevoValorIntegridad=Actual;
			}


			for (list<Atributo>::iterator itAtrib=Reg.Atributos.begin();itAtrib!=Reg.Atributos.end();++itAtrib){
				Atributo& Atrib=*itAtrib;
				//es el valor q va a ser remplazado, verifico q no se remplaze por el mismo valor
				//en ese caso no verifico integridad de baja ya q no va a ser borrado
				if ((Atrib.Nombre==RI.getNombreCampo()) && (Atrib.Valor!=NuevoValorIntegridad.Valor)){
					ClaveValor CV;
					CV.Clave=Atrib.Nombre;
					CV.Valor=Atrib.Valor;
					ValorControlaIntegridad.push_back(CV);
				}
			}
			if (!ValorControlaIntegridad.empty())
				if (!Integridad::VerificarIntegridad(RI,&ValorControlaIntegridad))
					return false;
		}
		return true;
	}

	bool Integridad::VerificarIntegridadBajaBorrado(RelacionIntegridad& RI,list<Registro>* ValoresOld){
		if (RI.getTipoIntegridad()==iAlta) return true;

		for (list<Registro>::iterator it=ValoresOld->begin();it!=ValoresOld->end();++it){
			Registro& Reg=*it;
			list<ClaveValor> ValorControlaIntegridad;
			

			for (list<Atributo>::iterator itAtrib=Reg.Atributos.begin();itAtrib!=Reg.Atributos.end();++itAtrib){
				Atributo& Atrib=*itAtrib;
				//es el valor q va a ser borrado
				if (Atrib.Nombre==RI.getNombreCampo()){
					ClaveValor CV;
					CV.Clave=Atrib.Nombre;
					CV.Valor=Atrib.Valor;
					ValorControlaIntegridad.push_back(CV);
				}
			}
			if (!ValorControlaIntegridad.empty())
				if (!Integridad::VerificarIntegridad(RI,&ValorControlaIntegridad))
					return false;
		}
		return true;
	}

	bool Integridad::VerificarIntegridad(RelacionIntegridad& RI,list<ClaveValor>* Valores){
		ClaveValor ClaveIntegridad;
		bool encontrado=false;
		for (list<ClaveValor>::iterator it=Valores->begin();it!=Valores->end();++it){
			ClaveValor& CVActual=*it;
			if (CVActual.Clave==RI.getNombreCampo()){
				encontrado=true;
				ClaveIntegridad=CVActual;
			}
		}
		if (!encontrado){
			return true;
		}else{
			CondicionCompuestaAND Condicion;
			list<std::string> Campos;
			Condicion.Subcondiciones.clear();
			CondicionCompuestaAND* CondicionCampo=new CondicionCompuestaAND;
			CondicionCampo->ValorCondicion.Nombre=RI.getNombreCampoClaseExterna();
			CondicionCampo->ValorCondicion.Valor=ClaveIntegridad.Valor;
			CondicionCampo->Simbolo=Igual;
			Condicion.Subcondiciones.push_back(CondicionCampo);
			Campos.clear();
			Campos.push_back(RI.getNombreCampoClaseExterna());
			stringstream * ArchIndices=ConexionCapaIndices::ArchIndicesSeleccion(RI.getNombreClase(),&Condicion,&Campos);
			stringstream Salida;
			ConexionCapaIndices::EjecutarLlamada(&Salida,ArchIndices);
			string str;
			
			getline(Salida,str);
			getline(Salida,str);
			int CantidadReg=atoi(str.c_str());
			if (RI.getTipoIntegridad()==iAlta){
				//si no levanto ningun registro es que no existe la referencia externa
				if (!CantidadReg)
					return false;
			}else{ //BAJA
				//si levanto algun registro es que existe alguien q me referencia
				//por lo tanto no puedo dar de baja
				if (CantidadReg)
					return false;
			}
			
		}
		
		return true;
	}
}
